home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 August: Tool Chest / Apple_Developer_Group_August_1996_Tool_Chest.iso / Sample Code / Snippets / Files / PutAwayVolumes / PutAwayVolumes.c < prev    next >
Encoding:
Text File  |  1996-05-24  |  7.1 KB  |  264 lines  |  [TEXT/CWIE]

  1.     //
  2.     //    This code sample demonstrates several ways to unmount a volume.
  3.     //
  4.     //        [1]        Call MoreFiles and have it take its best shot.
  5.     //
  6.     //        [2]        Augment MoreFiles with a little Finder-style interface
  7.     //                and some strategic trash-emptying.
  8.     //
  9.     //        [3]        Send an AppleEvent to Finder and have it do the whole thing.
  10.     //
  11.     //    A real strategy might use all of the above. Basically, the problem is
  12.     //    this: although UnmountVol has been patched so that some commonly open
  13.     //    files (mostly having to do with desktop info) are closed before the
  14.     //    volume unmounts, not all are, and in particular files associated
  15.     //    with the trash on shared volumes are not automagically closed.
  16.     //
  17.     //    Each of the three above-mentioned methods has its flaws.
  18.     //
  19.     //        [1]        It wouldn't be in the spirit of MoreFiles to empty
  20.     //                the trash silently when attempting to unmount, so it's
  21.     //                not surprising MoreFiles doesn't do it.
  22.     //
  23.     //        [2]        Getting confirmation from the user involves posting an
  24.     //                alert, which is not always easy for non-apps.
  25.     //
  26.     //        [3]        Requires the unmounter to send AppleEvents, which is
  27.     //                not always easy for non-apps, and may require user to
  28.     //                switch to Finder to confirm alerts, which also is not
  29.     //                always easy for non-apps.
  30.     //
  31.     //    Your program may have to combine methods to achieve the effect it
  32.     //    needs. And your program should be ready for the methods to fail --
  33.     //    not that you should expect a proper implementation to fail, but
  34.     //    your program shouldn't assume that it will not.
  35.     //
  36.     //    Of course, if some application other than Finder or At Ease has files
  37.     //    open on the volume, the volume simply will not unmount, and that's a
  38.     //    legitimate error condition.
  39.     //
  40.     //    Note this sample in its current state will unmount all AppleShare
  41.     //    volumes. The interesting function is PutAwayOneVolume, and it has
  42.     //    nothing to do with AppleShare in particular. The rest of the functions
  43.     //    are here simply to drive PutAwayOneVolume.
  44.     //
  45.     //    You may incorporate this sample code into your applications without
  46.     //    restriction, though the sample code has been provided "AS IS" and the
  47.     //    responsibility for its operation is 100% yours.  However, what you are
  48.     //    not permitted to do is to redistribute the source as "DTS Sample Code"
  49.     //    after having made changes. If you're going to re-distribute the source,
  50.     //    we require that you make it clear in the source that the code was
  51.     //    descended from Apple Sample Code, but that you've made changes.
  52.     //
  53.     //    Complaints and kudos to:
  54.     //
  55.     //        Pete Gontier
  56.     //        Apple Macintosh Developer Technical Support
  57.     //        <gurgle@apple.com>
  58.     //
  59.     //    Change history:
  60.     //
  61.     //        PG    03/20/96    St. Luther points out that 'hpbp->volumeParam.ioVFSID'
  62.     //                        is not a sufficient test for AppleShare; check the driver
  63.     //                        name instead; this makes the sample a little more accurate
  64.     //                        but a little less useful, since nobody specifies volumes
  65.     //                        by driver name. However, the portion of this code which
  66.     //                        cares about which volumes to unmount is only here to make
  67.     //                        the sample run anyway; users will have to adapt this code
  68.     //                        regardless; PutAwayOneVolume is the interesting code, and
  69.     //                        it's not affected by this change.
  70.     //
  71.     //        PG    03/20/96    PutAwayVolumes doesn't really need to know the names of the
  72.     //                        volumes it's indexing. Save some stack.
  73.     //
  74.     //        PG    03/21/96    Use MoreFiles version of UnmountAndEject. Keeping my own
  75.     //                        copy was just stupid, especially since I plan to use more
  76.     //                        of MoreFiles.
  77.     //
  78.     //        PG    03/21/96    After conversation with Jim, realized the AppleEvent
  79.     //                        strategy is not always best. This version makes use of
  80.     //                        semi-documented 'ReleaseFolder' call to deal with shared
  81.     //                        trash folders.
  82.     //
  83.  
  84. #define OLDROUTINELOCATIONS        0
  85. #define OLDROUTINENAMES            0
  86. #define SystemSevenOrLater        1
  87.  
  88. #ifndef __FILES__
  89. #    include <Files.h>
  90. #endif
  91.  
  92. #ifndef __LOWMEM__
  93. #    include <LowMem.h>
  94. #endif
  95.  
  96. #ifndef __DEVICES__
  97. #    include <Devices.h>
  98. #endif
  99.  
  100. #ifndef __PLSTRINGFUNCS__
  101. #    include <PLStringFuncs.h>
  102. #endif
  103.  
  104. #ifndef __PROCESSES__
  105. #    include <Processes.h>
  106. #endif
  107.  
  108. #include "PutAwayOneVolume.h"
  109.  
  110. #define USE_INTERNAL_CODE 1
  111.  
  112. //
  113. //    USE_INTERNAL_CODE controls whether we send the AppleEvent to Finder
  114. //    or use the internal code to unmount the volume ('ReleaseFolder').
  115. //
  116.  
  117. enum
  118. {
  119.     kCreatorCode_Finder = 'MACS',
  120.     kCreatorCode_AtEase = 'mfdr'
  121. };
  122.  
  123. static pascal OSErr GetCreatorOfFinderLikeProcess (OSType *processSignature)
  124. {
  125.     OSErr err = noErr;
  126.  
  127. #if !USE_INTERNAL_CODE
  128.  
  129.     ProcessSerialNumber        psn        = { kNoProcess, kNoProcess };
  130.     ProcessInfoRec            pir        = { sizeof (pir), nil };
  131.  
  132. #endif
  133.  
  134.     *processSignature = 0;
  135.  
  136. #if !USE_INTERNAL_CODE
  137.  
  138.     pir.processAppSpec = nil;
  139.  
  140.     for (;;)
  141.     {
  142.         err = GetNextProcess (&psn);
  143.         if (err)
  144.         {
  145.             if (err == procNotFound) err = noErr;
  146.             break;
  147.         }
  148.  
  149.         err = GetProcessInformation (&psn,&pir);
  150.         if (err) break;
  151.  
  152.         if (pir.processSignature == kCreatorCode_Finder || pir.processSignature == kCreatorCode_AtEase)
  153.         {
  154.             *processSignature = pir.processSignature;
  155.             break;
  156.         }
  157.     }
  158.  
  159. #endif
  160.  
  161.     return err;
  162. }
  163.  
  164. static pascal Boolean VolDriverNameIs (short vRefNum, ConstStr255Param potentialDriverName)
  165. {
  166.     Boolean result = false;
  167.  
  168.     const VCB *vcbQueueScanner = (const VCB *) GetVCBQHdr ( )->qHead;
  169.  
  170.     while (vcbQueueScanner)
  171.     {
  172.         if (vcbQueueScanner->vcbVRefNum == vRefNum)
  173.         {
  174.             short csParam [11];
  175.  
  176.             if (!Status (vcbQueueScanner->vcbDRefNum,1,csParam))
  177.             {
  178.                 DCtlHandle            dCtlHandle        = *(DCtlHandle *) csParam;
  179.                 DRVRHeaderPtr        drvrHeaderPtr    = (DRVRHeaderPtr) (**dCtlHandle).dCtlDriver;
  180.                 Boolean                isHandle        = (**dCtlHandle).dCtlFlags & dRAMBasedMask;
  181.                 ConstStr255Param    drvrName        = drvrHeaderPtr->drvrName;
  182.                 SInt8                hState;
  183.  
  184.                 //
  185.                 //    We lock the driver handle temporarily in case
  186.                 //    <PLStringFuncs.glue.lib> (which contains
  187.                 //    the implementation of PLstrcmp) lives in
  188.                 //    another (potentially unloaded) code segment.
  189.                 //
  190.  
  191.                 if (isHandle)
  192.                 {
  193.                     hState = HGetState ((Handle) drvrHeaderPtr);
  194.                     HLock ((Handle) drvrHeaderPtr);
  195.                     drvrName = (**(DRVRHeaderHandle)drvrHeaderPtr).drvrName;
  196.                 }
  197.  
  198.                 result = !PLstrcmp (potentialDriverName,drvrName);
  199.  
  200.                 if (isHandle)
  201.                     HSetState ((Handle) drvrHeaderPtr, hState);
  202.             }
  203.         }
  204.  
  205.         vcbQueueScanner = (const VCB *) (vcbQueueScanner->qLink);
  206.     }
  207.  
  208.     return result;
  209. }
  210.  
  211. static pascal OSErr PutAwayVolumes (const unsigned char *driverName)
  212. {
  213.     OSErr err = noErr;
  214.  
  215.     OSType finderLikeProcess;
  216.  
  217.     if (!(err = GetCreatorOfFinderLikeProcess (&finderLikeProcess)))
  218.     {
  219.         HParmBlkPtr hpbp = (HParmBlkPtr) NewPtrClear (sizeof (*hpbp));
  220.         if (!(err = MemError ( )))
  221.         {
  222.             hpbp->volumeParam.ioVolIndex = 1;
  223.     
  224.             for (;;)
  225.             {
  226.                 err = PBHGetVInfoSync (hpbp);
  227.                 if (err)
  228.                 {
  229.                     if (err == nsvErr) err = noErr;
  230.                     break;
  231.                 }
  232.     
  233.                 if (VolDriverNameIs (hpbp->volumeParam.ioVRefNum, driverName))
  234.                 {
  235.                     err = PutAwayOneVolume (hpbp->volumeParam.ioVRefNum, finderLikeProcess);
  236.                     if (err) break;
  237.                 }
  238.     
  239.                 hpbp->volumeParam.ioVolIndex += 1;
  240.             }
  241.     
  242.             DisposePtr ((Ptr) hpbp);
  243.             if (!err) err = MemError ( );
  244.         }
  245.     }
  246.  
  247.     return err;
  248. }
  249.  
  250. void main (void)
  251. {
  252.     MaxApplZone ( );
  253.     InitGraf (&(qd.thePort));
  254.     InitFonts ( );
  255.     InitWindows ( );
  256.     InitMenus ( );
  257.     TEInit ( );
  258.     InitDialogs (nil);
  259.  
  260. //    (void) PutAwayVolumes ("\p.Sony");
  261.  
  262.     (void) PutAwayVolumes ("\p.AFPTranslator");
  263. }
  264.